package com.cxx.framework.app.security;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.RequestMatcher;

import com.cxx.purchasecharge.component.bean.PCApplicationContext;

/**
 * 最核心的地方，就是提供某个资源对应的权限定义，即getAttributes方法返回的结果。 此类在初始化时，应该取到所有资源及其对应角色的定义。
 * 
 * @author xiang BeanFactoryAware, InitializingBean
 */
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource, InitializingBean
{
    private static final Logger LOGGER = Logger.getLogger (MyInvocationSecurityMetadataSourceService.class);
    private PCApplicationContext pcContext;
    private Map <RequestMatcher, Collection <ConfigAttribute>> resourceMap = new HashMap <RequestMatcher, Collection <ConfigAttribute>> ();

    @Override
    public Collection <ConfigAttribute> getAllConfigAttributes ()
    {
        LOGGER.debug ("getAllConfigAttributes executed");
        Set <ConfigAttribute> allAttributes = new HashSet <ConfigAttribute> ();
        for (Map.Entry <RequestMatcher, Collection <ConfigAttribute>> entry : resourceMap.entrySet ())
        {
            allAttributes.addAll (entry.getValue ());
        }
        return allAttributes;
    }

    // 根据URL，找到相关的权限配置。
    @Override
    public Collection <ConfigAttribute> getAttributes (Object object) throws IllegalArgumentException
    {
        resourceMap = pcContext.getSecurityResourceMap(false);
        // object 是一个URL，被用户请求的url
        final HttpServletRequest request = ((FilterInvocation) object).getRequest ();
        String requestUrl = ((FilterInvocation) object).getRequestUrl ();
        int firstQuestionMarkIndex = requestUrl.indexOf ("?");
        if (firstQuestionMarkIndex > 0)
        {
            requestUrl = requestUrl.substring (0, firstQuestionMarkIndex);
        }
        LOGGER.debug ("Request url: " + requestUrl);
        
        if (requestUrl.endsWith (".html") || requestUrl.endsWith (".do")
            || (requestUrl.startsWith ("/pdf") && -1 == requestUrl.lastIndexOf (".")))
        {
            Iterator <RequestMatcher> ite = resourceMap.keySet ().iterator ();
            while (ite.hasNext ())
            {
                RequestMatcher requestMatcher = ite.next ();
                if (requestMatcher.matches (request))
                {
                    return resourceMap.get (requestMatcher);
                }
            }
        }

        return null;
    }

    @Override
    public boolean supports (Class < ? > arg0)
    {
        return true;
    }

    public void setPcContext(PCApplicationContext pcContext)
    {
        this.pcContext = pcContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception
    {
        resourceMap = pcContext.getSecurityResourceMap(false);
    }

}
